#include "Explosion.h"
#include "Game.h"
#include "TexturesManager.h"
#include <ctime>

Explosion::Explosion()
{

}

Explosion::Explosion(const Explosion&)
{

}

Explosion::~Explosion()
{

}

void Explosion::Initialize()
{
	mIsActive = false;

	mBillboardFlame = new Billboard();
	mBillboardSmoke = new Billboard();

	Texture *textureExplosion = TexturesManager::Instance()->GetTexture("explosion.png");
	Texture *textureSmoke = TexturesManager::Instance()->GetTexture("smoke.png");

	BasicEffect* shader = Game::Instance()->GetShader();

	mBillboardFlame->Initialize(1,textureExplosion,shader);
	mBillboardSmoke->Initialize(EXPLOSION_SMOKE_COUNT,textureSmoke,shader);
}

void Explosion::Update(int pElapsedTime)
{
	if(!mIsActive) return;

	mLifeTime += pElapsedTime;
	if(mLifeTime > 1000)
	{
		mIsActive = false;
		return;
	}

	int imgNum = (mLifeTime / 100);
	mVerticesFlames[0].texturePosition = XMFLOAT2((imgNum % 4) * 0.25, (imgNum / 4) * 0.25);

	for(int i = 0;i < EXPLOSION_BURST_COUNT; i++)
	{
		mBursts[i].position.x += mBursts[i].velocity.x;
		mBursts[i].position.y += mBursts[i].velocity.y;
		mBursts[i].position.z += mBursts[i].velocity.z;

		mBursts[i].velocity.y -= 0.005;
		mBursts[i].velocity.x *= 0.95;
		mBursts[i].velocity.y *= 0.95;
		mBursts[i].velocity.z *= 0.95;
	}

	
	if(mLifeTime > mSmokeCount && mSmokeCount + 1 < EXPLOSION_SMOKE_COUNT)
	{
		for(int i = 0;i < EXPLOSION_BURST_COUNT; i++)
		{
			if(mSmokeCount + 1 < EXPLOSION_SMOKE_COUNT)
			{
				mSmokes[mSmokeCount].position = mBursts[i].position;
				mSmokes[mSmokeCount].velocity = XMFLOAT3(0,0,0);

				mVerticesSmokes[mSmokeCount].alpha = 1.0 - ((float)mLifeTime / 1000);
				mVerticesSmokes[mSmokeCount].size = XMFLOAT2(0.3,0.3);
				mVerticesSmokes[mSmokeCount].texturePosition = XMFLOAT2(0,0);
				mVerticesSmokes[mSmokeCount].textureSize = XMFLOAT2(1,1);

				mSmokeCount++;
			}
		}
	}

	for(int i = 0;i < mSmokeCount; i++)
	{
		mVerticesSmokes[i].alpha -= 0.05;
		if(mVerticesSmokes[i].alpha < 0) mVerticesSmokes[i].alpha = 0;

		mVerticesSmokes[i].position.y += 0.1;

		mVerticesSmokes[i].size.x += 0.2;
		mVerticesSmokes[i].size.y += 0.2;

		XMStoreFloat(&mSmokes[i].distance, XMVector3LengthSq(XMLoadFloat3(&Game::Instance()->GetCamera()->GetPosition()) - XMLoadFloat3(&mSmokes[i].position)));
	}

	for(int i = 1;i < mSmokeCount; i++)
	{
		if(mSmokes[i - 1].distance < mSmokes[i].distance)
		{
			ExplosionSmoke t;
			t = mSmokes[i - 1];
			mSmokes[i - 1] = mSmokes[i];
			mSmokes[i] = t;
		}
	}

	for(int i = 1;i < mSmokeCount; i++)
	{
		mVerticesSmokes[i].position = mSmokes[i].position;
	}
	mBillboardSmoke->UpdateBillboard(mVerticesSmokes, mSmokeCount);

	mBillboardFlame->UpdateBillboard(mVerticesFlames, 1);
}

void Explosion::StartExplosion(XMFLOAT3 pPosition, XMFLOAT3 pNormal)
{
	mIsActive = true;
	mSmokeCount = 0;
	mLifeTime = 0;

	for(int i = 0;i < EXPLOSION_BURST_COUNT; i++)
	{
		mBursts[i].position = pPosition;
		float vX = (pNormal.x + (0.002 * ((rand() % 1000) - 500))) * 0.5;
		float vY = (pNormal.y + (0.002 * ((rand() % 1000) - 500))) * 0.5;
		float vZ = (pNormal.z + (0.002 * ((rand() % 1000) - 500))) * 0.5;
		mBursts[i].velocity = XMFLOAT3(vX, vY, vZ);
	}

	Update(0);

	mVerticesFlames[0].position = pPosition;
	mVerticesFlames[0].size = XMFLOAT2(5,5);
	mVerticesFlames[0].alpha = 1;
	mVerticesFlames[0].texturePosition = XMFLOAT2(0, 0);
	mVerticesFlames[0].textureSize = XMFLOAT2(0.25f, 0.25f);
	mBillboardFlame->UpdateBillboard(mVerticesFlames, 1);
}

void Explosion::Render()
{
	if(!mIsActive) return;
	CDirect3D::Instance()->DisableWriteDepthStencil();
	mBillboardFlame->Render();
	mBillboardSmoke->Render();
	CDirect3D::Instance()->EnableDepthStencil();
}